#ifndef NUM_DIR_LIGHTS
#define NUM_DIR_LIGHTS 3
#endif

#ifndef NUM_POINT_LIGHTS
#define NUM_POINT_LIGHTS 0
#endif

#ifndef NUM_SPOT_LIGHTS
#define NUM_SPOT_LIGHTS 0
#endif

#include "lightUtil.hlsl"

Texture2D    gDiffuseMap : register(t0);
//Texture2D    gSpecularMap : register(t1);

SamplerState gsamPointWrap        : register(s0);
SamplerState gsamPointClamp       : register(s1);
SamplerState gsamLinearWrap       : register(s2);
SamplerState gsamLinearClamp      : register(s3);
SamplerState gsamAnisotropicWrap  : register(s4);
SamplerState gsamAnisotropicClamp : register(s5);

cbuffer cbPerObject: register(b0)
{
	float4x4 gWorld;
	float4x4 gTexTransform;
};

cbuffer cbPass: register(b1)
{
	float4x4 gView;
	float4x4 gInvView;
	float4x4 gProj;
	float4x4 gInvProj;
	float4x4 gViewProj;
	float4x4 gInvViewProj;
	float3 gEyePosW;
	float cbPerObjectPad1;
	float2 gRenderTargetSize;
	float2 gInvRenderTargetSize;
	float gNearZ;
	float gFarZ;
	float gTotalTime;
	float gDeltaTime;
	float4 gAmbientLight;

	Light gLights[MaxLights];
};

cbuffer cbMaterial : register(b2)
{
	float4   gDiffuseAlbedo;
	float3   gFresnelR0;
	float    gRoughness;
	float4x4 gMatTransform;
};


struct VertexIn
{
	float3 posL  : POSITION;
	float3 normal : NORMAL;
	float2 texC : TEXCOORD;
};

struct PSInput
{
	float4 posH : SV_POSITION;
	float3 posW : POSITION;
	float3 normalW : NORMAL;
	float2 texC : TEXCOORD;
};

PSInput VSMain(VertexIn vin)
{
	PSInput vout;
	float4 posW = mul(float4(vin.posL, 1.0f), gWorld);
	
	vout.posW = posW.xyz;
	vout.normalW = mul(vin.normal, (float3x3)gWorld);
	vout.posH = mul(posW, gViewProj);

	float4 texC = mul(float4(vin.texC, 0.0, 1.0f), gTexTransform);
	vout.texC = mul(texC, gMatTransform).xy;

	return vout;
}

float4 PSMain(PSInput pin) : SV_TARGET
{		
	float3 diff = pow(gDiffuseMap.Sample(gsamAnisotropicWrap, pin.texC).xyz, 2.2);
	float4 diffuseAlbedo = float4(diff, 1.0f)  * gDiffuseAlbedo;

	// Interpolating normal can unnormalize it, so renormalize it.
	pin.normalW = normalize(pin.normalW);

	// Vector from point being lit to eye. 
	float3 toEyeW = normalize(gEyePosW - pin.posW);

	// Light terms.
	float4 ambient = gAmbientLight * diffuseAlbedo;

	const float shininess = 1.0f - gRoughness;
	Material mat = { diffuseAlbedo, gFresnelR0, shininess };
	float3 shadowFactor = 1.0f;
	float4 directLight = ComputeLighting(gLights, mat, pin.posW,
		pin.normalW, toEyeW, shadowFactor);

	float4 litColor = ambient + directLight;

	litColor = pow(litColor, 1.0f/2.2f);
	// Common convention to take alpha from diffuse albedo.
	litColor.a = diffuseAlbedo.a;//1.0f;

	return litColor;//float4(pin.normalW,1.0);litColor
}